package zincsearch

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"
)

func (c *APIClient) NewContext(ctx context.Context) context.Context {
	if ctx == nil {
		ctx = context.Background()
	}
	ctx = context.WithValue(ctx, ContextBasicAuth, BasicAuth{
		UserName: c.GetConfig().UserName,
		Password: c.GetConfig().Password,
	})
	return ctx
}

func (c *APIClient) HttpSearch(index string, resAryPointer any, query string) (total int64, err error) {
	var request *http.Request
	request, err = http.NewRequest(
		"POST",
		fmt.Sprintf("%s/es/%s/_search", c.GetConfig().Url, index),
		strings.NewReader(query),
	)
	if err != nil {
		return 0, err
	}

	request.SetBasicAuth(c.GetConfig().UserName, c.GetConfig().Password)
	request.Header.Set("Content-Type", "application/json")

	var resp *http.Response
	resp, err = http.DefaultClient.Do(request)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		err = errors.New(fmt.Sprintf("zincsearch http error:%d", resp.StatusCode))
		return 0, err
	}

	var bytes []byte
	bytes, err = io.ReadAll(resp.Body)
	if err != nil {
		return 0, err
	}

	var response = new(MetaSearchResponse)
	err = json.Unmarshal(bytes, response)
	if err != nil {
		return 0, err
	}

	if resAryPointer == nil {
		return int64(*response.Hits.Total.Value), nil
	}

	err = response.ScanSource(resAryPointer)
	return int64(*response.Hits.Total.Value), err
}

func (c *APIClient) HttpAddDoc(index string, data string) (id string, err error) {
	var request *http.Request
	request, err = http.NewRequest(
		"POST",
		fmt.Sprintf("%s/api/%s/_doc", c.GetConfig().Url, index),
		strings.NewReader(data),
	)
	if err != nil {
		return "", err
	}

	request.SetBasicAuth(c.GetConfig().UserName, c.GetConfig().Password)
	request.Header.Set("Content-Type", "application/json")

	var resp *http.Response
	resp, err = http.DefaultClient.Do(request)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		err = errors.New(fmt.Sprintf("zincsearch http error:%d", resp.StatusCode))
		return "", err
	}

	//{"message":"ok","id":"25yqYaTR49W","_id":"25yqYaTR49W","_index":"assign_user","_version":1,"_seq_no":0,"_primary_term":0,"result":"created"}
	var bAry []byte
	bAry, err = io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	var dic = map[string]interface{}{}
	err = json.Unmarshal(bAry, &dic)
	if err != nil {
		return "", err
	}
	v, _ := dic["id"].(string)
	return v, nil
}

func (c *APIClient) HttpUpdateDoc(index string, docId string, data string) (err error) {
	var request *http.Request
	request, err = http.NewRequest(
		"POST",
		fmt.Sprintf("%s/api/%s/_update/%s", c.GetConfig().Url, index, docId),
		strings.NewReader(data),
	)
	if err != nil {
		return err
	}

	request.SetBasicAuth(c.GetConfig().UserName, c.GetConfig().Password)
	request.Header.Set("Content-Type", "application/json")

	var resp *http.Response
	resp, err = http.DefaultClient.Do(request)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		err = errors.New(fmt.Sprintf("zincsearch http error:%d", resp.StatusCode))
		return err
	}

	return nil
}
